package nikee.util.text;

public class HexUtil {
	final static char hexorder[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

	public static String toHexString(int value) {
		long conv = value < 0 ? (((long) (Integer.MAX_VALUE) + 1) * 2) + value : value;
		return toHexString(conv, 8);
	}

	public static String toHexString(byte value) {
		long conv = value < 0 ? ((long) (Byte.MAX_VALUE + 1) * 2) + value : value;
		return toHexString(conv, 2);
	}

	public static String toHexString(short value) {
		long conv = value < 0 ? ((long) (Short.MAX_VALUE + 1) * 2) + value : value;
		return toHexString(conv, 4);
	}

	static String toHexString(long value, int length) {
		StringBuffer sb = new StringBuffer();
		// sb.append("0x");
		for (int i = length; i > 0; i--) {
			int pow = power(0x10, i);
			int idx = (int) (value / pow);
			value = value % pow;
			sb.append(hexorder[idx]);
		}
		return sb.toString();
	}

	static int power(int value, int times) {
		int ret = value;
		times--;
		if (times < 1)
			return 1;
		for (int i = 1; i < times; i++)
			ret *= value;
		return ret;
	}

	public static long parseHexString(String str) throws Exception {
		return parseHexString(str, 0, str.length());
	}

	public static long parseHexString(String str, int sidx, int length) throws Exception {
		int sum = 0;
		str.toUpperCase();
		for (int i = sidx; i < length; i++) {
			if (sum * 16 > Long.MAX_VALUE) {
				throw new Exception("0x" + str.substring(sidx, length) + " is out of manageable range(" + Long.MIN_VALUE + "~" + Long.MAX_VALUE + ")");
			}

			char ch = str.charAt(i);
			if (ch >= '0' && ch <= '9') {
				sum = sum * 16 + (ch - '0');
			} else if (ch >= 'A' && ch <= 'F') {
				sum = sum * 16 + (ch + 10 - 'A');
			} else {
				throw new Exception(ch + " in string '" + str.substring(sidx, length) + "' is not hex code.");
			}
		}
		return sum;
	}

	public static int toInt(byte value) {
		return value < 0 ? ((int) (Byte.MAX_VALUE + 1) * 2) + value : value;
	}

	public static int toInt(char val) {
		byte value = (byte) val;
		return value < 0 ? ((int) (Byte.MAX_VALUE + 1) * 2) + value : value;
	}

	public static char[] hexStringToCharArray(String str, boolean isLittleEndian) throws Exception {
		int length = str.length() / 2;
		char[] ret = new char[length];
		if (isLittleEndian) {
			for (int i = 0; i < length; i++) {
				ret[i] = (char) parseHexString(str, i * 2, ((i + 1) * 2) < str.length() ? (i + 1) * 2 : str.length());
			}
			return ret;
		} else {
			return ret;
		}
	}
}
